// 增强版3D渲染器 - 支持GLB、OBJ、FBX、STL、USDZ、MP4等多种格式
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
// 🔥 新增：多格式加载器
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'
import { USDZLoader } from 'three/examples/jsm/loaders/USDZLoader.js'
// MP4视频纹理支持
import { VideoTexture } from 'three'
// 🔥 新增：ZIP文件解压支持
import JSZip from 'jszip'
// 🔥 新增：导入URL转换工具
import { convertToProxyUrl, isHunyuanResource, logUrlConversion } from '@/util/replaceUrl'

export class EnhancedThreeRenderer {
    constructor(canvas) {
        this.canvas = canvas

        // 核心对象
        this.scene = null
        this.camera = null
        this.renderer = null
        this.controls = null

        // 🔥 新增：多格式加载器
        this.loaders = {
            gltf: null,
            obj: null,
            mtl: null,
            fbx: null,
            stl: null,
            usdz: null
        }
        this.dracoLoader = null

        // 模型和环境
        this.currentModel = null
        this.modelGroup = null
        this.lights = []
        this.gridHelper = null
        this.axesHelper = null

        // 状态
        this.isInitialized = false
        this.animationId = null
        self.autoRotate = false
        this.isFullscreen = false

        // 模型边界信息
        this.modelBoundingBox = null
        this.modelCenter = new THREE.Vector3()
        this.modelSize = new THREE.Vector3()

        // 全屏相关
        this.originalCameraSettings = null
        this.fullscreenResizeTimeout = null

        // 性能监控
        this.frameCount = 0
        this.lastPerformanceCheck = Date.now()
        this.averageFPS = 0

        // 🔥 新增：URL转换功能
        this.enableUrlProxy = true

        // 🔥 新增：支持的格式映射
        this.supportedFormats = {
            'GLB': { loader: 'gltf', hasAnimation: true, hasTextures: true },
            'GLTF': { loader: 'gltf', hasAnimation: true, hasTextures: true },
            'OBJ': { loader: 'obj', hasAnimation: false, hasTextures: true, supportZip: true },
            'FBX': { loader: 'fbx', hasAnimation: true, hasTextures: true },
            'STL': { loader: 'stl', hasAnimation: false, hasTextures: false },
            'USDZ': { loader: 'usdz', hasAnimation: true, hasTextures: true },
            'MP4': { loader: 'video', hasAnimation: true, hasTextures: false },
            // 🔥 新增：ZIP 格式支持
            'ZIP': { loader: 'obj', hasAnimation: false, hasTextures: true, supportZip: true }
        }

        // 🔥 新增：动画相关
        this.mixer = null
        this.animations = []
        this.activeAction = null
        this.clock = new THREE.Clock()

        // 🔥 新增：视频纹理相关
        this.videoTextures = []
    }

    // URL转换方法
    convertUrlIfNeeded(url) {
        if (!this.enableUrlProxy || !url) {
            return url
        }

        if (isHunyuanResource(url)) {
            const proxyUrl = convertToProxyUrl(url)
            logUrlConversion('3D渲染器模型加载', url, proxyUrl)
            return proxyUrl
        }

        return url
    }

    setUrlProxyEnabled(enabled) {
        this.enableUrlProxy = enabled
        console.log('[EnhancedRenderer] URL代理功能:', enabled ? '已启用' : '已禁用')
    }

    // 🔥 新增：判断文件格式
    detectFileFormat(url) {
        const urlLower = url.toLowerCase()

        if (urlLower.includes('.glb')) return 'GLB'
        if (urlLower.includes('.gltf')) return 'GLTF'
        if (urlLower.includes('.obj')) return 'OBJ'
        if (urlLower.includes('.fbx')) return 'FBX'
        if (urlLower.includes('.stl')) return 'STL'
        if (urlLower.includes('.usdz')) return 'USDZ'
        if (urlLower.includes('.mp4')) return 'MP4'
        if (urlLower.includes('.zip')) return 'ZIP' // 可能包含OBJ等文件

        // 默认尝试GLB格式
        return 'GLB'
    }

    // 初始化渲染器
    async initialize() {
        try {
            this.initRenderer()
            this.initScene()
            this.initCamera()
            this.initControls()
            this.initLights()
            this.initHelpers()
            this.initLoaders() // 🔥 更新：初始化多格式加载器
            this.setupEvents()
            this.startRenderLoop()

            this.isInitialized = true
            console.log('[EnhancedRenderer] 渲染器初始化完成，支持格式:', Object.keys(this.supportedFormats).join(', '))
            return true
        } catch (error) {
            console.error('[EnhancedRenderer] 初始化失败:', error)
            return false
        }
    }

    initRenderer() {
        this.renderer = new THREE.WebGLRenderer({
            canvas: this.canvas,
            antialias: true,
            alpha: false,
            preserveDrawingBuffer: true,
            powerPreference: 'high-performance'
        })

        const devicePixelRatio = Math.min(window.devicePixelRatio, 2)
        this.renderer.setPixelRatio(devicePixelRatio)
        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight)
        this.renderer.setClearColor(0x0f0f0f)

        this.renderer.shadowMap.enabled = true
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
        this.renderer.outputColorSpace = THREE.SRGBColorSpace
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping
        this.renderer.toneMappingExposure = 1.0
    }

    initScene() {
        this.scene = new THREE.Scene()
        this.scene.background = new THREE.Color(0x0f0f0f)
        this.modelGroup = new THREE.Group()
        this.scene.add(this.modelGroup)
    }

    initCamera() {
        const aspect = this.canvas.clientWidth / this.canvas.clientHeight
        this.camera = new THREE.PerspectiveCamera(60, aspect, 0.01, 1000)
        this.camera.position.set(0, 0, 5)
        this.saveCameraSettings()
    }

    initControls() {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement)
        this.controls.enableDamping = true
        this.controls.dampingFactor = 0.05
        this.controls.minDistance = 0.1
        this.controls.maxDistance = 100
        this.controls.maxPolarAngle = Math.PI
        this.controls.screenSpacePanning = false
        this.controls.rotateSpeed = 1.0
        this.controls.panSpeed = 1.0
        this.controls.zoomSpeed = 1.0
    }

    initLights() {
        this.lights.forEach(light => this.scene.remove(light))
        this.lights = []

        // 环境光
        const ambientLight = new THREE.AmbientLight(0x404040, 0.8)
        this.scene.add(ambientLight)
        this.lights.push(ambientLight)

        // 主光源
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0)
        directionalLight.position.set(10, 10, 5)
        directionalLight.castShadow = true
        directionalLight.shadow.mapSize.width = 2048
        directionalLight.shadow.mapSize.height = 2048
        directionalLight.shadow.camera.near = 0.1
        directionalLight.shadow.camera.far = 50
        directionalLight.shadow.camera.left = -10
        directionalLight.shadow.camera.right = 10
        directionalLight.shadow.camera.top = 10
        directionalLight.shadow.camera.bottom = -10
        this.scene.add(directionalLight)
        this.lights.push(directionalLight)

        // 补光
        const fillLight = new THREE.DirectionalLight(0xffffff, 0.6)
        fillLight.position.set(-10, 5, -10)
        this.scene.add(fillLight)
        this.lights.push(fillLight)

        // 顶光
        const topLight = new THREE.DirectionalLight(0xffffff, 0.4)
        topLight.position.set(0, 10, 0)
        this.scene.add(topLight)
        this.lights.push(topLight)

        // 底部反射光
        const bottomLight = new THREE.DirectionalLight(0x6699ff, 0.3)
        bottomLight.position.set(0, -8, 0)
        this.scene.add(bottomLight)
        this.lights.push(bottomLight)

        // 底部环境光
        const bottomAmbient = new THREE.DirectionalLight(0x404040, 0.25)
        bottomAmbient.position.set(5, -5, 5)
        this.scene.add(bottomAmbient)
        this.lights.push(bottomAmbient)

        // 侧面补光
        const sideLight1 = new THREE.DirectionalLight(0xffffff, 0.2)
        sideLight1.position.set(8, 0, -8)
        this.scene.add(sideLight1)
        this.lights.push(sideLight1)

        const sideLight2 = new THREE.DirectionalLight(0xffffff, 0.2)
        sideLight2.position.set(-8, 0, 8)
        this.scene.add(sideLight2)
        this.lights.push(sideLight2)
    }

    initHelpers() {
        this.gridHelper = new THREE.GridHelper(20, 40, 0x444444, 0x222222)
        this.gridHelper.visible = true
        this.scene.add(this.gridHelper)

        this.axesHelper = new THREE.AxesHelper(5)
        this.axesHelper.visible = false
        this.scene.add(this.axesHelper)
    }

    // 🔥 更新：初始化多格式加载器
    initLoaders() {
        // DRACO解码器
        this.dracoLoader = new DRACOLoader()
        this.dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/')

        // GLTF/GLB加载器
        this.loaders.gltf = new GLTFLoader()
        this.loaders.gltf.setDRACOLoader(this.dracoLoader)

        // OBJ加载器
        this.loaders.obj = new OBJLoader()

        // MTL材质加载器（用于OBJ）
        this.loaders.mtl = new MTLLoader()

        // FBX加载器
        this.loaders.fbx = new FBXLoader()

        // STL加载器
        this.loaders.stl = new STLLoader()

        // USDZ加载器（如果可用）
        try {
            this.loaders.usdz = new USDZLoader()
        } catch (e) {
            console.warn('[EnhancedRenderer] USDZ加载器不可用:', e.message)
            this.loaders.usdz = null
        }

        console.log('[EnhancedRenderer] 已初始化加载器:', Object.keys(this.loaders).filter(key => this.loaders[key]))
    }

    setupEvents() {
        const resizeObserver = new ResizeObserver((entries) => {
            for (const entry of entries) {
                if (this.fullscreenResizeTimeout) {
                    clearTimeout(this.fullscreenResizeTimeout)
                }
                this.fullscreenResizeTimeout = setTimeout(() => {
                    this.onWindowResize()
                }, 50)
            }
        })
        resizeObserver.observe(this.canvas)
        this.resizeObserver = resizeObserver

        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                this.pauseRendering()
            } else {
                this.resumeRendering()
            }
        })
    }

    startRenderLoop() {
        const render = () => {
            // 性能监控
            this.frameCount++
            const now = Date.now()
            if (now - this.lastPerformanceCheck > 1000) {
                this.averageFPS = this.frameCount
                this.frameCount = 0
                this.lastPerformanceCheck = now
            }

            // 🔥 新增：更新动画
            if (this.mixer) {
                const delta = this.clock.getDelta()
                this.mixer.update(delta)
            }

            // 自动旋转
            if (this.autoRotate && this.currentModel) {
                this.currentModel.rotation.y += 0.01
            }

            // 更新控制器
            if (this.controls) {
                this.controls.update()
            }

            // 渲染场景
            if (this.renderer && this.scene && this.camera) {
                this.renderer.render(this.scene, this.camera)
            }

            this.animationId = requestAnimationFrame(render)
        }
        render()
    }

    pauseRendering() {
        if (this.animationId) {
            cancelAnimationFrame(this.animationId)
            this.animationId = null
        }
    }

    resumeRendering() {
        if (!this.animationId) {
            this.startRenderLoop()
        }
    }

    // 全屏相关方法
    setFullscreenMode(isFullscreen) {
        const wasFullscreen = this.isFullscreen
        this.isFullscreen = isFullscreen

        if (isFullscreen && !wasFullscreen) {
            this.enterFullscreenMode()
        } else if (!isFullscreen && wasFullscreen) {
            this.exitFullscreenMode()
        }
    }

    enterFullscreenMode() {
        this.saveCameraSettings()
        if (this.controls) {
            this.controls.rotateSpeed = 0.8
            this.controls.panSpeed = 0.8
            this.controls.zoomSpeed = 0.9
        }
        const pixelRatio = Math.min(window.devicePixelRatio, 1.5)
        this.renderer.setPixelRatio(pixelRatio)
        setTimeout(() => this.onWindowResize(), 100)
    }

    exitFullscreenMode() {
        if (this.controls) {
            this.controls.rotateSpeed = 1.0
            this.controls.panSpeed = 1.0
            this.controls.zoomSpeed = 1.0
        }
        const pixelRatio = Math.min(window.devicePixelRatio, 2)
        this.renderer.setPixelRatio(pixelRatio)
        setTimeout(() => this.onWindowResize(), 100)
    }

    saveCameraSettings() {
        if (this.camera) {
            this.originalCameraSettings = {
                position: this.camera.position.clone(),
                fov: this.camera.fov,
                aspect: this.camera.aspect,
                near: this.camera.near,
                far: this.camera.far
            }

            if (this.controls) {
                this.originalCameraSettings.target = this.controls.target.clone()
                this.originalCameraSettings.minDistance = this.controls.minDistance
                this.originalCameraSettings.maxDistance = this.controls.maxDistance
            }
        }
    }

    // 🔥 新增：解压ZIP文件
    async extractZipFile(url) {
        try {
            console.log('[EnhancedRenderer] 开始解压ZIP文件:', url)

            const response = await fetch(url)
            const arrayBuffer = await response.arrayBuffer()
            const zip = await JSZip.loadAsync(arrayBuffer)

            const files = {}
            const promises = []

            zip.forEach((relativePath, zipEntry) => {
                if (!zipEntry.dir) {
                    const extension = relativePath.split('.').pop().toLowerCase()
                    promises.push(
                        zipEntry.async('blob').then(blob => {
                            const objectUrl = URL.createObjectURL(blob)
                            files[relativePath] = {
                                url: objectUrl,
                                extension: extension,
                                name: relativePath
                            }
                        })
                    )
                }
            })

            await Promise.all(promises)
            console.log('[EnhancedRenderer] ZIP解压完成，文件:', Object.keys(files))

            return files
        } catch (error) {
            console.error('[EnhancedRenderer] ZIP解压失败:', error)
            throw error
        }
    }

    // 🔥 新增：加载OBJ模型（支持ZIP）
    async loadOBJModel(modelUrl, options = {}) {
        const { onProgress, onLoaded, onError } = options

        try {
            let objUrl = modelUrl
            let mtlUrl = null
            let isFromZip = false

            // 检查是否是ZIP文件
            if (modelUrl.toLowerCase().includes('.zip')) {
                const files = await this.extractZipFile(modelUrl)
                isFromZip = true

                // 查找OBJ和MTL文件
                const objFile = Object.values(files).find(f => f.extension === 'obj')
                const mtlFile = Object.values(files).find(f => f.extension === 'mtl')

                if (!objFile) {
                    throw new Error('ZIP文件中未找到OBJ文件')
                }

                objUrl = objFile.url
                mtlUrl = mtlFile ? mtlFile.url : null

                console.log('[EnhancedRenderer] 从ZIP中提取:', { obj: objFile.name, mtl: mtlFile?.name })
            } else {
                // 尝试查找对应的MTL文件
                const baseUrl = modelUrl.replace(/\.obj$/i, '')
                mtlUrl = baseUrl + '.mtl'
            }

            let model

            // 如果有MTL文件，先加载材质
            if (mtlUrl) {
                try {
                    const materials = await new Promise((resolve, reject) => {
                        this.loaders.mtl.load(mtlUrl, resolve, undefined, reject)
                    })

                    materials.preload()
                    this.loaders.obj.setMaterials(materials)
                    console.log('[EnhancedRenderer] MTL材质加载成功')
                } catch (mtlError) {
                    console.warn('[EnhancedRenderer] MTL加载失败，使用默认材质:', mtlError.message)
                }
            }

            // 加载OBJ模型
            model = await new Promise((resolve, reject) => {
                this.loaders.obj.load(objUrl, resolve, (progress) => {
                    if (progress.total === 0) return
                    const percent = Math.min((progress.loaded / progress.total) * 100, 100)
                    if (onProgress) onProgress(percent)
                }, reject)
            })

            // 清理临时URL
            if (isFromZip) {
                URL.revokeObjectURL(objUrl)
                if (mtlUrl) URL.revokeObjectURL(mtlUrl)
            }

            return model

        } catch (error) {
            console.error('[EnhancedRenderer] OBJ加载失败:', error)
            if (onError) onError(error)
            throw error
        }
    }

    // 🔥 新增：加载FBX模型
    async loadFBXModel(modelUrl, options = {}) {
        const { onProgress, onLoaded, onError } = options

        try {
            const model = await new Promise((resolve, reject) => {
                this.loaders.fbx.load(modelUrl, resolve, (progress) => {
                    if (progress.total === 0) return
                    const percent = Math.min((progress.loaded / progress.total) * 100, 100)
                    if (onProgress) onProgress(percent)
                }, reject)
            })

            // 🔥 新增：处理FBX动画
            if (model.animations && model.animations.length > 0) {
                this.mixer = new THREE.AnimationMixer(model)
                this.animations = model.animations

                console.log('[EnhancedRenderer] FBX动画数量:', model.animations.length)

                // 播放第一个动画
                if (this.animations.length > 0) {
                    this.activeAction = this.mixer.clipAction(this.animations[0])
                    this.activeAction.play()
                }
            }

            return model

        } catch (error) {
            console.error('[EnhancedRenderer] FBX加载失败:', error)
            if (onError) onError(error)
            throw error
        }
    }

    // 🔥 新增：加载STL模型
    async loadSTLModel(modelUrl, options = {}) {
        const { onProgress, onLoaded, onError } = options

        try {
            const geometry = await new Promise((resolve, reject) => {
                this.loaders.stl.load(modelUrl, resolve, (progress) => {
                    if (progress.total === 0) return
                    const percent = Math.min((progress.loaded / progress.total) * 100, 100)
                    if (onProgress) onProgress(percent)
                }, reject)
            })

            // STL只有几何体，需要创建材质和网格
            const material = new THREE.MeshStandardMaterial({
                color: 0x888888,
                metalness: 0.3,
                roughness: 0.4
            })

            const model = new THREE.Mesh(geometry, material)
            model.castShadow = true
            model.receiveShadow = true

            // 计算法向量
            geometry.computeVertexNormals()

            return model

        } catch (error) {
            console.error('[EnhancedRenderer] STL加载失败:', error)
            if (onError) onError(error)
            throw error
        }
    }

    // 🔥 新增：加载USDZ模型
    async loadUSDZModel(modelUrl, options = {}) {
        const { onProgress, onLoaded, onError } = options

        if (!this.loaders.usdz) {
            throw new Error('USDZ加载器不可用')
        }

        try {
            const model = await new Promise((resolve, reject) => {
                this.loaders.usdz.load(modelUrl, resolve, (progress) => {
                    if (progress.total === 0) return
                    const percent = Math.min((progress.loaded / progress.total) * 100, 100)
                    if (onProgress) onProgress(percent)
                }, reject)
            })

            return model

        } catch (error) {
            console.error('[EnhancedRenderer] USDZ加载失败:', error)
            if (onError) onError(error)
            throw error
        }
    }

    // 🔥 新增：加载MP4视频作为纹理
    async loadVideoTexture(videoUrl, options = {}) {
        const { onProgress, onLoaded, onError } = options

        try {
            // 创建视频元素
            const video = document.createElement('video')
            video.src = videoUrl
            video.crossOrigin = 'anonymous'
            video.loop = true
            video.muted = true
            video.playsInline = true

            // 等待视频加载
            await new Promise((resolve, reject) => {
                video.addEventListener('loadeddata', resolve)
                video.addEventListener('error', reject)
                video.load()
            })

            // 创建视频纹理
            const videoTexture = new VideoTexture(video)
            videoTexture.minFilter = THREE.LinearFilter
            videoTexture.magFilter = THREE.LinearFilter

            // 创建应用视频纹理的平面
            const geometry = new THREE.PlaneGeometry(4, 3)
            const material = new THREE.MeshBasicMaterial({
                map: videoTexture,
                transparent: false,
                side: THREE.DoubleSide
            })

            const model = new THREE.Mesh(geometry, material)

            // 保存视频引用以便控制播放
            this.videoTextures.push({ video, texture: videoTexture })

            // 自动播放
            video.play().catch(e => {
                console.warn('[EnhancedRenderer] 视频自动播放失败:', e.message)
            })

            console.log('[EnhancedRenderer] 视频纹理创建成功:', {
                duration: video.duration,
                dimensions: `${video.videoWidth}x${video.videoHeight}`
            })

            return model

        } catch (error) {
            console.error('[EnhancedRenderer] MP4加载失败:', error)
            if (onError) onError(error)
            throw error
        }
    }

    // 修复后的 loadModel 方法
    async loadModel(modelUrl, options = {}) {
        console.log('[EnhancedRenderer] 开始加载模型:', modelUrl)
        const { onProgress, onLoaded, onError, format } = options

        // 🔥 修复：将 actualModelUrl 初始化移到 try 块外面
        let actualModelUrl = modelUrl // 默认使用原始URL

        try {
            this.clearModel()

            // 🔥 修复：安全地转换URL
            try {
                actualModelUrl = this.convertUrlIfNeeded(modelUrl)
            } catch (urlError) {
                console.warn('[EnhancedRenderer] URL转换失败，使用原始URL:', urlError.message)
                actualModelUrl = modelUrl
            }

            // 检测文件格式
            const detectedFormat = format || this.detectFileFormat(actualModelUrl)
            const formatInfo = this.supportedFormats[detectedFormat]

            if (!formatInfo) {
                throw new Error(`不支持的文件格式: ${detectedFormat}`)
            }

            console.log('[EnhancedRenderer] 检测到格式:', detectedFormat, '使用加载器:', formatInfo.loader)

            let model

            // 根据格式选择对应的加载方法
            switch (formatInfo.loader) {
                case 'gltf':
                    model = await new Promise((resolve, reject) => {
                        this.loaders.gltf.load(actualModelUrl, (gltf) => {
                            const loadedModel = gltf.scene.clone()

                            // 处理GLTF动画
                            if (gltf.animations && gltf.animations.length > 0) {
                                this.mixer = new THREE.AnimationMixer(loadedModel)
                                this.animations = gltf.animations

                                console.log('[EnhancedRenderer] GLTF动画数量:', gltf.animations.length)

                                // 播放第一个动画
                                if (this.animations.length > 0) {
                                    this.activeAction = this.mixer.clipAction(this.animations[0])
                                    this.activeAction.play()
                                }
                            }

                            resolve(loadedModel)
                        }, (progress) => {
                            if (progress.total === 0) return
                            const percent = Math.min((progress.loaded / progress.total) * 100, 100)
                            if (onProgress) onProgress(percent)
                        }, reject)
                    })
                    break

                case 'obj':
                    model = await this.loadOBJModel(actualModelUrl, { onProgress, onLoaded, onError })
                    break

                case 'fbx':
                    model = await this.loadFBXModel(actualModelUrl, { onProgress, onLoaded, onError })
                    break

                case 'stl':
                    model = await this.loadSTLModel(actualModelUrl, { onProgress, onLoaded, onError })
                    break

                case 'usdz':
                    model = await this.loadUSDZModel(actualModelUrl, { onProgress, onLoaded, onError })
                    break

                case 'video':
                    model = await this.loadVideoTexture(actualModelUrl, { onProgress, onLoaded, onError })
                    break

                default:
                    throw new Error(`不支持的加载器类型: ${formatInfo.loader}`)
            }

            // 统一处理模型
            this.processModel(model)
            this.modelGroup.add(model)
            this.currentModel = model

            // 计算模型边界信息
            this.updateModelBounds()

            // 调整相机以适应模型
            this.fitCameraToModel()

            const info = this.calculateModelInfo()
            if (onLoaded) onLoaded(info)

            console.log('[EnhancedRenderer] 模型加载完成:', {
                format: detectedFormat,
                vertices: info.vertices,
                faces: info.faces,
                hasAnimations: this.animations.length > 0,
                hasVideoTextures: this.videoTextures.length > 0,
                isProxyUrl: actualModelUrl !== modelUrl
            })

            return true
        } catch (error) {
            console.error('[EnhancedRenderer] 模型加载失败:', error)

            // 🔥 修复：现在 actualModelUrl 总是已定义的，安全检查代理URL回退
            if (actualModelUrl !== modelUrl && isHunyuanResource(modelUrl)) {
                console.warn('[EnhancedRenderer] 代理URL加载失败，尝试使用原始URL...')
                try {
                    return await this.loadModel(modelUrl, { ...options, format })
                } catch (fallbackError) {
                    console.error('[EnhancedRenderer] 原始URL也加载失败:', fallbackError)
                    if (onError) onError(fallbackError)
                    return false
                }
            }

            if (onError) onError(error)
            return false
        }
    }

    // 更新模型边界信息
    updateModelBounds() {
        if (!this.currentModel) {
            this.modelBoundingBox = null
            return
        }

        this.modelBoundingBox = new THREE.Box3().setFromObject(this.currentModel)
        this.modelBoundingBox.getCenter(this.modelCenter)
        this.modelBoundingBox.getSize(this.modelSize)
    }

    processModel(model) {
        model.traverse((child) => {
            if (child.isMesh) {
                child.castShadow = true
                child.receiveShadow = true

                if (child.material) {
                    if (Array.isArray(child.material)) {
                        child.material.forEach(mat => this.processMaterial(mat))
                    } else {
                        this.processMaterial(child.material)
                    }
                }

                if (child.geometry && !child.geometry.attributes.normal) {
                    child.geometry.computeVertexNormals()
                }
            }
        })

        // 计算原始边界
        const box = new THREE.Box3().setFromObject(model)
        const size = box.getSize(new THREE.Vector3())
        const center = box.getCenter(new THREE.Vector3())

        // 将模型移动到原点
        model.position.sub(center)

        // 智能缩放
        const maxDimension = Math.max(size.x, size.y, size.z)
        let targetSize = 4

        if (this.isFullscreen) {
            targetSize *= 1.2
        }

        if (maxDimension < 0.1) {
            targetSize = 2
        } else if (maxDimension < 1) {
            targetSize = 3
        } else if (maxDimension < 10) {
            targetSize = 4
        } else {
            targetSize = 5
        }

        const scale = targetSize / maxDimension
        model.scale.setScalar(scale)

        console.log('[EnhancedRenderer] 模型处理信息:', {
            originalSize: size,
            originalCenter: center,
            maxDimension: maxDimension,
            targetSize: targetSize,
            scale: scale,
            isFullscreen: this.isFullscreen
        })
    }

    processMaterial(material) {
        if (material.transparent || material.alphaTest > 0) {
            material.side = THREE.DoubleSide
        }

        if (material.isMeshStandardMaterial || material.isMeshPhysicalMaterial) {
            material.envMapIntensity = 1.0
            material.metalness = Math.min(material.metalness, 0.9)
            material.roughness = Math.max(material.roughness, 0.1)
        }

        material.needsUpdate = true
    }

    fitCameraToModel() {
        if (!this.currentModel || !this.modelBoundingBox) {
            this.resetCameraToDefault()
            return
        }

        const box = new THREE.Box3().setFromObject(this.currentModel)
        const size = box.getSize(new THREE.Vector3())
        const center = box.getCenter(new THREE.Vector3())

        const maxDim = Math.max(size.x, size.y, size.z)
        const fov = this.camera.fov * (Math.PI / 180)
        const distance = maxDim / (2 * Math.tan(fov / 2))
        let safeDistance = distance * (this.isFullscreen ? 1.6 : 1.8)

        const cameraDistance = Math.max(safeDistance, 1.0)
        this.camera.position.set(
            center.x + cameraDistance * 0.7,
            center.y + cameraDistance * 0.5,
            center.z + cameraDistance * 0.7
        )

        this.camera.lookAt(center)

        this.controls.target.copy(center)
        this.controls.minDistance = cameraDistance * 0.2
        this.controls.maxDistance = cameraDistance * (this.isFullscreen ? 6 : 4)
        this.controls.update()

        this.updateGridSize(maxDim)
    }

    updateGridSize(modelSize) {
        if (this.gridHelper) {
            this.scene.remove(this.gridHelper)
        }

        let gridSize = Math.max(modelSize * 3, 10)
        let divisions = Math.max(Math.floor(gridSize), 20)

        if (this.isFullscreen) {
            gridSize *= 1.5
            divisions = Math.min(divisions * 1.2, 60)
        }

        this.gridHelper = new THREE.GridHelper(gridSize, divisions, 0x444444, 0x222222)
        this.gridHelper.visible = true
        this.scene.add(this.gridHelper)
    }

    resetCameraToDefault() {
        const defaultDistance = this.isFullscreen ? 6 : 5
        this.camera.position.set(3, 3, defaultDistance)
        this.camera.lookAt(0, 0, 0)
        this.controls.target.set(0, 0, 0)
        this.controls.minDistance = 0.5
        this.controls.maxDistance = this.isFullscreen ? 150 : 100
        this.controls.update()
    }

    // 🔥 新增：动画控制方法
    playAnimation(index = 0) {
        if (!this.mixer || !this.animations[index]) {
            console.warn('[EnhancedRenderer] 无可用动画')
            return false
        }

        if (this.activeAction) {
            this.activeAction.stop()
        }

        this.activeAction = this.mixer.clipAction(this.animations[index])
        this.activeAction.play()

        console.log('[EnhancedRenderer] 播放动画:', index, this.animations[index].name)
        return true
    }

    pauseAnimation() {
        if (this.activeAction && this.activeAction.isRunning()) {
            this.activeAction.paused = !this.activeAction.paused
            return !this.activeAction.paused
        }
        return false
    }

    stopAnimation() {
        if (this.activeAction) {
            this.activeAction.stop()
            return true
        }
        return false
    }

    getAnimationList() {
        return this.animations.map((clip, index) => ({
            index,
            name: clip.name || `Animation ${index + 1}`,
            duration: clip.duration
        }))
    }

    // 🔥 新增：视频控制方法
    playVideo() {
        this.videoTextures.forEach(({ video }) => {
            video.play().catch(e => console.warn('视频播放失败:', e))
        })
    }

    pauseVideo() {
        this.videoTextures.forEach(({ video }) => {
            if (video.paused) {
                video.play()
            } else {
                video.pause()
            }
        })
    }

    stopVideo() {
        this.videoTextures.forEach(({ video }) => {
            video.pause()
            video.currentTime = 0
        })
    }

    // 清理模型
    clearModel() {
        // 停止动画
        if (this.mixer) {
            this.mixer.stopAllAction()
            this.mixer = null
        }
        this.animations = []
        this.activeAction = null

        // 清理视频纹理
        this.videoTextures.forEach(({ video, texture }) => {
            video.pause()
            video.src = ''
            texture.dispose()
        })
        this.videoTextures = []

        if (this.modelGroup) {
            while (this.modelGroup.children.length > 0) {
                const child = this.modelGroup.children[0]
                this.modelGroup.remove(child)
                this.disposeObject(child)
            }
        }

        this.currentModel = null
        this.modelBoundingBox = null
        this.modelCenter.set(0, 0, 0)
        this.modelSize.set(0, 0, 0)
    }

    disposeObject(object) {
        object.traverse((child) => {
            if (child.geometry) {
                child.geometry.dispose()
            }
            if (child.material) {
                if (Array.isArray(child.material)) {
                    child.material.forEach(mat => this.disposeMaterial(mat))
                } else {
                    this.disposeMaterial(child.material)
                }
            }
        })
    }

    disposeMaterial(material) {
        for (const key in material) {
            const value = material[key]
            if (value && typeof value === 'object' && 'minFilter' in value) {
                value.dispose()
            }
        }
        material.dispose()
    }

    calculateModelInfo() {
        if (!this.currentModel) return null

        let vertices = 0
        let faces = 0

        this.currentModel.traverse((child) => {
            if (child.isMesh && child.geometry) {
                if (child.geometry.attributes.position) {
                    vertices += child.geometry.attributes.position.count
                }
                if (child.geometry.index) {
                    faces += child.geometry.index.count / 3
                } else if (child.geometry.attributes.position) {
                    faces += child.geometry.attributes.position.count / 3
                }
            }
        })

        return {
            vertices: Math.round(vertices),
            faces: Math.round(faces),
            size: this.modelSize,
            center: this.modelCenter,
            averageFPS: this.averageFPS,
            animations: this.getAnimationList(),
            hasVideo: this.videoTextures.length > 0
        }
    }

    // 动态光照控制方法
    adjustLightIntensity(lightType, intensity) {
        switch (lightType) {
            case 'ambient':
                if (this.lights[0]) this.lights[0].intensity = intensity
                break
            case 'main':
                if (this.lights[1]) this.lights[1].intensity = intensity
                break
            case 'fill':
                if (this.lights[2]) this.lights[2].intensity = intensity
                break
            case 'top':
                if (this.lights[3]) this.lights[3].intensity = intensity
                break
            case 'bottom':
                if (this.lights[4]) this.lights[4].intensity = intensity
                break
            case 'bottomAmbient':
                if (this.lights[5]) this.lights[5].intensity = intensity
                break
        }
    }

    setLightingPreset(preset) {
        switch (preset) {
            case 'bright':
                this.adjustLightIntensity('ambient', 1.0)
                this.adjustLightIntensity('main', 1.2)
                this.adjustLightIntensity('bottom', 0.4)
                this.adjustLightIntensity('bottomAmbient', 0.3)
                break
            case 'soft':
                this.adjustLightIntensity('ambient', 0.9)
                this.adjustLightIntensity('main', 0.8)
                this.adjustLightIntensity('bottom', 0.35)
                this.adjustLightIntensity('bottomAmbient', 0.4)
                break
            case 'dramatic':
                this.adjustLightIntensity('ambient', 0.5)
                this.adjustLightIntensity('main', 1.5)
                this.adjustLightIntensity('bottom', 0.2)
                this.adjustLightIntensity('bottomAmbient', 0.1)
                break
            case 'balanced':
            default:
                this.adjustLightIntensity('ambient', 0.8)
                this.adjustLightIntensity('main', 1.0)
                this.adjustLightIntensity('bottom', 0.3)
                this.adjustLightIntensity('bottomAmbient', 0.25)
                break
        }
        console.log(`[EnhancedRenderer] 应用光照预设: ${preset}`)
    }

    setCameraMode(mode) {
        if (!this.camera) return

        const aspect = this.canvas.clientWidth / this.canvas.clientHeight
        const currentPos = this.camera.position.clone()
        const currentTarget = this.controls.target.clone()
        const currentDistance = currentPos.distanceTo(currentTarget)

        if (mode === 'orthographic') {
            const frustumSize = currentDistance * Math.tan(this.camera.fov * Math.PI / 180 / 2) * 2
            this.camera = new THREE.OrthographicCamera(
                frustumSize * aspect / -2,
                frustumSize * aspect / 2,
                frustumSize / 2,
                frustumSize / -2,
                0.01, 1000
            )
        } else {
            this.camera = new THREE.PerspectiveCamera(60, aspect, 0.01, 1000)
        }

        this.camera.position.copy(currentPos)
        this.camera.lookAt(currentTarget)

        this.controls.object = this.camera
        this.controls.target.copy(currentTarget)
        this.controls.update()
    }

    setRenderMode(mode) {
        if (!this.currentModel) return

        this.currentModel.traverse((child) => {
            if (child.isMesh && child.material) {
                const materials = Array.isArray(child.material) ? child.material : [child.material]
                materials.forEach(material => {
                    material.wireframe = (mode === 'wireframe')
                    material.needsUpdate = true
                })
            }
        })
    }

    setAutoRotate(enabled) {
        this.autoRotate = enabled
    }

    toggleGrid(enabled) {
        if (this.gridHelper) {
            this.gridHelper.visible = enabled
        }
    }

    toggleAxes(enabled) {
        if (this.axesHelper) {
            this.axesHelper.visible = enabled
        }
    }

    resetCamera() {
        if (this.currentModel && this.modelBoundingBox) {
            this.fitCameraToModel()
        } else {
            this.resetCameraToDefault()
        }
    }

    captureScreenshot(width = 1920, height = 1080) {
        if (!this.renderer || !this.camera || !this.scene) return null

        const originalSize = this.renderer.getSize(new THREE.Vector2())
        const originalPixelRatio = this.renderer.getPixelRatio()

        try {
            if (this.isFullscreen) {
                width = Math.max(width, 2560)
                height = Math.max(height, 1440)
            }

            this.renderer.setPixelRatio(1)
            this.renderer.setSize(width, height, false)

            const aspect = width / height
            if (this.camera.isPerspectiveCamera) {
                this.camera.aspect = aspect
            } else if (this.camera.isOrthographicCamera) {
                const frustumHeight = this.camera.top - this.camera.bottom
                const frustumWidth = frustumHeight * aspect
                this.camera.left = frustumWidth / -2
                this.camera.right = frustumWidth / 2
            }
            this.camera.updateProjectionMatrix()

            this.renderer.render(this.scene, this.camera)
            const dataURL = this.renderer.domElement.toDataURL('image/png')

            return dataURL
        } catch (error) {
            console.error('[EnhancedRenderer] 截图失败:', error)
            return null
        } finally {
            this.renderer.setPixelRatio(originalPixelRatio)
            this.renderer.setSize(originalSize.x, originalSize.y, false)

            const currentAspect = originalSize.x / originalSize.y
            if (this.camera.isPerspectiveCamera) {
                this.camera.aspect = currentAspect
            } else if (this.camera.isOrthographicCamera) {
                const frustumHeight = this.camera.top - this.camera.bottom
                const frustumWidth = frustumHeight * currentAspect
                this.camera.left = frustumWidth / -2
                this.camera.right = frustumWidth / 2
            }
            this.camera.updateProjectionMatrix()
        }
    }

    onWindowResize() {
        if (!this.renderer || !this.camera) return

        const width = this.canvas.clientWidth
        const height = this.canvas.clientHeight

        if (this.camera.isPerspectiveCamera) {
            this.camera.aspect = width / height
        } else if (this.camera.isOrthographicCamera) {
            const aspect = width / height
            const frustumHeight = this.camera.top - this.camera.bottom
            const frustumWidth = frustumHeight * aspect

            this.camera.left = frustumWidth / -2
            this.camera.right = frustumWidth / 2
        }

        this.camera.updateProjectionMatrix()
        this.renderer.setSize(width, height)

        if (this.currentModel && this.modelSize) {
            const maxDim = Math.max(this.modelSize.x, this.modelSize.y, this.modelSize.z)
            this.updateGridSize(maxDim)
        }
    }

    // 🔥 新增：获取支持的格式列表
    getSupportedFormats() {
        return Object.keys(this.supportedFormats).map(format => ({
            format,
            ...this.supportedFormats[format]
        }))
    }

    // 性能监控方法
    getPerformanceStats() {
        return {
            averageFPS: this.averageFPS,
            isFullscreen: this.isFullscreen,
            renderCalls: this.renderer.info.render.calls,
            triangles: this.renderer.info.render.triangles,
            geometries: this.renderer.info.memory.geometries,
            textures: this.renderer.info.memory.textures,
            urlProxyEnabled: this.enableUrlProxy,
            supportedFormats: Object.keys(this.supportedFormats),
            hasAnimations: this.animations.length > 0,
            hasVideoTextures: this.videoTextures.length > 0
        }
    }

    dispose() {
        console.log('[EnhancedRenderer] 开始清理资源')

        // 停止渲染
        if (this.animationId) {
            cancelAnimationFrame(this.animationId)
        }

        // 清理超时
        if (this.fullscreenResizeTimeout) {
            clearTimeout(this.fullscreenResizeTimeout)
        }

        // 清理模型
        this.clearModel()

        // 清理控制器
        if (this.controls) {
            this.controls.dispose()
        }

        // 清理事件
        if (this.resizeObserver) {
            this.resizeObserver.disconnect()
        }

        // 清理渲染器
        if (this.renderer) {
            this.renderer.dispose()
        }

        // 清理加载器
        if (this.dracoLoader) {
            this.dracoLoader.dispose()
        }

        // 清理场景
        if (this.scene) {
            this.scene.traverse((object) => {
                this.disposeObject(object)
            })
            this.scene.clear()
        }

        this.isInitialized = false
        console.log('[EnhancedRenderer] 资源清理完成')
    }
}